#include <avr/io.h>
#include <avr/interrupt.h>

#include "global.h"
#include "xbuffer.h"
#include "xuart.h"

xBuffer uartRxBuf;
xBuffer uartTxBuf;

static unsigned char uartRxData[UART_RX_BUF_SIZE];
static unsigned char uartTxData[UART_TX_BUF_SIZE];
unsigned int    uartRxOverflowCount;

void uartInit(unsigned long baudRate){
    unsigned int _ubrr;

    bufferInit(&uartRxBuf, uartRxData, UART_RX_BUF_SIZE);
    bufferInit(&uartTxBuf, uartTxData, UART_TX_BUF_SIZE);

    // set baud rate
    // the formula is valid only if asynchronous double speed mode is used (U2X = 1)
    _ubrr = F_CPU/(8UL*baudRate) - 1;
    UBRRL = _ubrr;
    UBRRH = (_ubrr >> 8);

    // communication format: 8 data bits, no parity, 1 stop bit (8N1)
    UCSRA = _BV(U2X);
    UCSRC = _BV(UCSZ0) | _BV(UCSZ1); //8 data bits
    UCSRB = _BV(RXCIE) | _BV(RXEN) | _BV(TXEN); //enable interrupts, Rx, and Tx

	sei();
}

void uartStartTransmission(){
    UCSRB |= _BV(UDRIE);
}

//Rx completed service routine
ISR (USART_RX_vect){
    unsigned char c;
    c = UDR;
    if(!bufferWrite(&uartRxBuf, &c, 1)){
        //no storage space, increment overflow count
        uartRxOverflowCount++;
    }
}

//UART Data Register empty service routine
ISR (USART_UDRE_vect){
    //static unsigned short status = 0;

    unsigned char c;

    //PORTB = status >> 8;
    //status++;

    if( bufferRead(&uartTxBuf, &c, 1) ){
        UDR = c;
    }else{
        //diable UDRE interrupt
        UCSRB = UCSRB & (~_BV(UDRIE));
    }

}

